package com.filters;

import com.common.util.rsa.RsaKeys;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.http.HttpServletRequestWrapper;
import com.netflix.zuul.http.ServletInputStreamWrapper;
import com.service.RsaService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.HashMap;

@Component
public class RSARequestFilter extends ZuulFilter {

	private static Logger log = LoggerFactory.getLogger(RSARequestFilter.class);

	@Autowired
	private RsaService rsaService;

	@Override
	public String filterType() {
		return FilterConstants.PRE_TYPE;
	}

	@Override
	public int filterOrder() {
		return FilterConstants.PRE_DECORATION_FILTER_ORDER + 1;
	}

	@Override
	public boolean shouldFilter() {

		return true;
	}

	@Override
	public Object run() {

		RequestContext ctx = RequestContext.getCurrentContext();
		HttpServletRequest request = ctx.getRequest();
		log.info(String.format("%s >>> %s", request.getMethod(), request
				.getRequestURL().toString()));
		// String data = request.getParameter("data");

		ClientHttpResponse response = null;

		BufferedReader br;
		String requestBody = null;
		HashMap params = null;
		byte[] encryptData;
		try {

			// 客户端传的是string对象
//			StringBuffer sb = new StringBuffer("");
//			String temp;
//
//			br = new BufferedReader(new InputStreamReader(
//					(ServletInputStream) request.getInputStream(), "utf-8"));
//			while ((temp = br.readLine()) != null) {
//				sb.append(temp);
//			}
//
//			br.close();
//			requestBody = sb.toString();
			
			InputStream in = ctx.getRequest().getInputStream();  
			requestBody = StreamUtils.copyToString(in, Charset.forName("UTF-8"));  

			System.out.println("rsa加密算法：" + rsaService.getRsaAlgorithm());
			System.out.println("从request中取出来的data：" + requestBody);

			String decryptData = rsaService.RSADecryptDataPEM(requestBody,
					RsaKeys.getServerPrvKeyPkcs8());

			// 客户端传的是byte数组
			// ServletInputStream sis = (ServletInputStream)
			// request.getInputStream();
			// BufferedInputStream bufin = new BufferedInputStream(sis);
			// int buffSize = 1024;
			// ByteArrayOutputStream out = new ByteArrayOutputStream(buffSize);
			// byte[] temp = new byte[buffSize];
			// int size = 0;
			// while ((size = bufin.read(temp)) != -1) {
			// out.write(temp, 0, size);
			// }
			// bufin.close();
			//
			// encryptData = out.toByteArray();
			// requestBody = new String(encryptData, "utf-8");
			//
			// String decryptData = rsaService.RSADecryptDataBytes(encryptData,
			// RsaKeys.getServerPrvKeyPkcs8());

			System.out.println("解密后的data：" + decryptData);

			// 将参数塞进request body
			final byte[] reqBodyBytes = decryptData.getBytes();
			
			ctx.setRequest( new HttpServletRequestWrapper(request) {
				
				@Override
				public ServletInputStream getInputStream() throws IOException {
					return new ServletInputStreamWrapper(reqBodyBytes);
				}

				@Override
				public int getContentLength() {
					return reqBodyBytes.length;
				}

				@Override
				public long getContentLengthLong() {
					return reqBodyBytes.length;
				}
			});

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		// if(ret.getCode() != RetCode.SUCCESS)
		// {
		// Gson gson = new Gson();
		// String jsonStr = gson.toJson(ret);
		// ctx.setSendZuulResponse(false);
		// ctx.setResponseStatusCode(200);
		//
		// try {
		// ctx.getResponse().getWriter().write(jsonStr);
		// }catch (Exception e){
		// e.printStackTrace();
		// }
		//
		// return null;
		// }

		log.info("ok");
		return null;
	}
}